home *** CD-ROM | disk | FTP | other *** search
- #
- # ElGamal.py : ElGamal encryption/decryption and signatures
- #
- # Part of the Python Cryptography Toolkit
- #
- # Distribute and use freely; there are no restrictions on further
- # dissemination and usage except those imposed by the laws of your
- # country of residence. This software is provided "as is" without
- # warranty of fitness for use or suitability for any purpose, express
- # or implied. Use at your own risk or not at all.
- #
-
- __revision__ = "$Id: ElGamal.py,v 1.9 2003/04/04 19:44:26 akuchling Exp $"
-
- from Crypto.PublicKey.pubkey import *
- from Crypto.Util import number
-
- class error (Exception):
- pass
-
- # Generate an ElGamal key with N bits
- def generate(bits, randfunc, progress_func=None):
- """generate(bits:int, randfunc:callable, progress_func:callable)
-
- Generate an ElGamal key of length 'bits', using 'randfunc' to get
- random data and 'progress_func', if present, to display
- the progress of the key generation.
- """
- obj=ElGamalobj()
- # Generate prime p
- if progress_func:
- progress_func('p\n')
- obj.p=bignum(getPrime(bits, randfunc))
- # Generate random number g
- if progress_func:
- progress_func('g\n')
- size=bits-1-(ord(randfunc(1)) & 63) # g will be from 1--64 bits smaller than p
- if size<1:
- size=bits-1
- while (1):
- obj.g=bignum(getPrime(size, randfunc))
- if obj.g < obj.p:
- break
- size=(size+1) % bits
- if size==0:
- size=4
- # Generate random number x
- if progress_func:
- progress_func('x\n')
- while (1):
- size=bits-1-ord(randfunc(1)) # x will be from 1 to 256 bits smaller than p
- if size>2:
- break
- while (1):
- obj.x=bignum(getPrime(size, randfunc))
- if obj.x < obj.p:
- break
- size = (size+1) % bits
- if size==0:
- size=4
- if progress_func:
- progress_func('y\n')
- obj.y = pow(obj.g, obj.x, obj.p)
- return obj
-
- def construct(tuple):
- """construct(tuple:(long,long,long,long)|(long,long,long,long,long)))
- : ElGamalobj
- Construct an ElGamal key from a 3- or 4-tuple of numbers.
- """
-
- obj=ElGamalobj()
- if len(tuple) not in [3,4]:
- raise error, 'argument for construct() wrong length'
- for i in range(len(tuple)):
- field = obj.keydata[i]
- setattr(obj, field, tuple[i])
- return obj
-
- class ElGamalobj(pubkey):
- keydata=['p', 'g', 'y', 'x']
-
- def _encrypt(self, M, K):
- a=pow(self.g, K, self.p)
- b=( M*pow(self.y, K, self.p) ) % self.p
- return ( a,b )
-
- def _decrypt(self, M):
- if (not hasattr(self, 'x')):
- raise error, 'Private key not available in this object'
- ax=pow(M[0], self.x, self.p)
- plaintext=(M[1] * inverse(ax, self.p ) ) % self.p
- return plaintext
-
- def _sign(self, M, K):
- if (not hasattr(self, 'x')):
- raise error, 'Private key not available in this object'
- p1=self.p-1
- if (GCD(K, p1)!=1):
- raise error, 'Bad K value: GCD(K,p-1)!=1'
- a=pow(self.g, K, self.p)
- t=(M-self.x*a) % p1
- while t<0: t=t+p1
- b=(t*inverse(K, p1)) % p1
- return (a, b)
-
- def _verify(self, M, sig):
- v1=pow(self.y, sig[0], self.p)
- v1=(v1*pow(sig[0], sig[1], self.p)) % self.p
- v2=pow(self.g, M, self.p)
- if v1==v2:
- return 1
- return 0
-
- def size(self):
- "Return the maximum number of bits that can be handled by this key."
- return number.size(self.p) - 1
-
- def has_private(self):
- """Return a Boolean denoting whether the object contains
- private components."""
- if hasattr(self, 'x'):
- return 1
- else:
- return 0
-
- def publickey(self):
- """Return a new key object containing only the public information."""
- return construct((self.p, self.g, self.y))
-
-
- object=ElGamalobj
-